/**
 * 建立 MQTT 连接，并将相关对象包装成一个服务
 */
import { getLogger } from '@gnlab/utils'
import { type Subscription } from 'rxjs'
import config from '@/config'
import MQTTConnection from '@/lib/mqtt'
import { bizAccountIds } from '@/services/auth'
import { TopicCommunicate } from '@/services/common/qywx-mqtt'

const logger = getLogger('mqtt')

/**
 * 适配部署需求
 * 1. 若 config 里指定了 MQTT_PORT，始终使用这个值
 * 2. 若 config 里没指定：
 *    1. 若当前 HTTP 端口小于 10000，使用默认 MQTT_PORT
 *    2. 若当前 HTTP 端口大于等于 10000，使用 HTTP 端口 + 1 作为 MQTT_PORT
 *       （这主要是为了适配部分客户需要外网访问，会用一个很高的端口来配置反向代理）
 */
const DEFAULT_MQTT_PORT = 9002
function getMQTTPort() {
  if (config.MQTT_PORT !== null) return config.MQTT_PORT

  const port = location.port.length ? parseInt(location.port, 10) : null
  return port !== null && port > 10000 ? port + 1 : DEFAULT_MQTT_PORT
}

export class MQTT {
  // 不能写 window.location，因为 web worker 里读不到 window 对象
  private readonly address = `${location.protocol === 'https:' ? 'wss' : 'ws'}://${
    config.MQTT_HOST || location.hostname
  }:${getMQTTPort()}${config.MQTT_PATH}`

  connection = new MQTTConnection(this.address)

  status = this.connection.status

  connected = this.connection.connected

  communicate = new TopicCommunicate(this.connection, bizAccountIds)

  prepared = this.communicate.prepared

  private subscription: Subscription | null = null
  log() {
    this.stopLog()
    this.subscription = this.communicate.all().subscribe(message => {
      logger.debug(message)
    })
  }
  stopLog() {
    this.subscription?.unsubscribe()
  }
}
